import numpy as na
from ..dicom.orderDICOMFiles import orderDICOMFiles

class viewableImgSeq(viewableImg):
    """a class built around a numpy array that includes functionality for
    projecting, rescaling, and rendering to a viewable image"""

    def __init__(self, **kwargs):
        """constructor for viewableImgSeq class"""
        viewableImg.__init__(self, **kwargs)
        self.dir = kwargs.pop("dir",None)
        if( self.dir == None ):
            self.dir = os.getcwd()
        self.wslice = {'xy':0}
        self.cview = 'xy'
        self.viewtypes = ['local']

        self.dicomFiles = orderDICOMFiles(self.dir)
        if( not self.dicomFiles ):
            return
        self.mode = self.data.ndim
        scls = kwargs.pop('scls',[1,1])
        #print "scls=",scls
        scls = na.array(scls,na.float32)/min(scls)
        self.sscls = {'xy':[scls[0],scls[1]]}
        self.views = {'xy':0}
        self.projections = {'max':na.max}
        self.numSlices = {'xy':0}
        self.slice = self.data
        self.subdata = self.slice
        self.pt = {'xy':0}
        self.dsize = {'xy':(self.data.shape[1],self.data.shape[0])}
            self.wslice['xz'] = 0
            
            self.dsize = {'xy':(self.data.shape[2],self.data.shape[1]),
                          'xz':(self.data.shape[2],self.data.shape[0]),
                          'yz':(self.data.shape[1],self.data.shape[0])}
            self.numSlices = {'xy':len(self.dicomFiles)}
            self.views = {'xy':0}
            self.plims = {'xy':[0,1]}
            self.axis = {'xy':0}
            self.slice = self.getDSlice()
            self.subdata = self.slice

        self.projs = {}
        self.FlipLR = False
        self.FlipUD = False
        self.cproj = na.max # current projection
        self.lproj = 'max'
        self.viewtype = self.viewtypes[0]

        self.getProjections()
        self.setWinLev()
        self.setView()
    def getFlipLR(self):
        return self.FlipLR
    def getFlipUD(self):
        return self.FlipUD
    def getDSize(self):
        return self.dsize[self.cview]
    def getScale(self):
        return self.sscls[self.cview]
    def getAxis(self):
        return self.axis[self.cview]
    def getDSlice(self):
        s = self.getSlice()
        if( self.cview == 'xy' ):
            return self.data[s,:,:]
        elif( self.cview == 'xz' ):
            return self.data[:,s,:]
        else:
            return self.data[:,:,s]
    def setWindow(self,winvalue):
        self.colorSettings[self.lproj]['wc'] = winvalue
    def setLevel(self,levvalue):
        self.colorSettings[self.lproj]['lc'] = levvalue
    def getWindow(self):
        return self.colorSettings[self.lproj]['wc']
    def getColorSettings(self):
        return self.colorSettings[self.lproj]
    def getLevel(self):
        return self.colorSettings[self.lproj]['lc']
    def getNumSlices(self):
        return self.numSlices[self.cview]
    def getPlims(self):
        return self.plims[self.cview]
    def setPlims(self):
        plims = [max(0,self.getSlice()-self.getPT()),
                 min(self.getNumSlices(),self.getSlice()+self.getPT()+1)]
        self.plims[self.cview] = plims
    def setWinLev(self):
        return
    def getProjections(self):
        pass
    def setSubImg(self):
        self.subdata = self.data

    def getValue(self,p):
        """return the voxel/pixel value associated with the point p"""
        try:
            if( self.mode == 2 ):
                return self.data[p[1],p[0]]
            else:
                return self.data[p[2],p[1],p[0]]
        except Exception, error:
            print "failed in getValue()", error
    def ProjectSlab(self):
        self.slice = self.data

    def getViewType(self):
        """return the specified view type (e.g., 'global', 'local')"""
        return self.viewtype
    def setViewType(self,vt='local'):
        pass
    def setProjection(self,proj="max"):
        pass
    def setView(self, v='xy'):
        pass
    def getView(self):
        return self.cview
    def getData(self):
        if( self.mode == 3 ):
            self.cproj = self.projections[self.lproj]
            if( self.viewtype == 'global' ):
                self.slice = self.projs[self.lproj][self.cview]
            else:
                #print "using ProjectSlab"
                self.ProjectSlab()

    def setSlice(self,slice):
        self.wslice[self.cview] = slice
        self.setPlims()
        
    def getSlice(self):
        return self.wslice[self.cview]
    def setPT(self,thick):
        self.pt[self.cview] = thick
        self.setPlims()
    def getPT(self):
        return self.pt[self.cview]
    def getWinLevValues(self,data=None):
        if(data == None ):
            data = self.data
        imax = data.max()
        imin = data.min()
        wh = (imax-imin)
        wl = 1
        lh = (imax+imin)/2+(imax-imin)-1
        ll = (imax+imin)/2-(imax-imin)
        vals = {'ll':ll,'lh':lh,'wh':wh,'wl':wl,'wc':(wl+wh/3),'lc':(ll+lh)/2}
        return vals
    def toggleFlipUD(self):
        self.FlipUD = not self.FlipUD
    def toggleFlipLR(self):
        self.FlipLR = not self.FlipLR
    def flipSlice(self):
        if(self.FlipUD):
            self.rawbuffer = self.rawbuffer[::-1,:]
        if(self.FlipLR):
            self.rawbuffer = self.rawbuffer[:,::-1]
    def win_lev(self, maxc = 255 ):
        try:
            win = self.getWindow()
            lev = self.getLevel()
            m = maxc / (2.0*win)
            o = m*(lev-win)
            temp= na.clip((m*self.slice-o),0,maxc).astype(na.uint8)
            return temp
        except Exception, error:
            print "failed in win_lev() ", error
    def winlevelimage(self):
        try:
            temp = self.win_lev()
            # why is my slice coming out upside down?
            temp = na.transpose(na.array((temp,temp,temp),na.uint8),(1,2,0))
            self.rawbuffer = na.require(temp,na.uint8,'CO')
            self.flipSlice()

        except Exception, error:
            print "failed in winlevelimage", error
    def getRawBuffer(self):
        return self.rawbuffer

    def getMaxInView(self,x,y):
        if( self.mode == 2 ):
            return -1
        else:
            pl = self.getPlims() 
            if( pl[1]-pl[0] == 1 ):
                return self.getSlice()
            else:
                if( self.cview == 'xy' ):
                    zz = na.argmax(self.subdata[pl[0]:pl[1],y,x])+pl[0]
                elif( self.cview == 'xz' ):
                    zz = na.argmax(self.subdata[y,pl[0]:pl[1],x])+pl[0]
                else:
                    zz = na.argmax(self.subdata[y,x,pl[0]:pl[1]])+pl[0]
                return zz

